package com.jichangxiu.common.utils;

import cn.hutool.core.util.StrUtil;
import com.jichangxiu.common.cache.RedisService;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * LockUtils:
 *
 * @author Jcx
 * @create 2023-04-03 21:49
 */
@Component
public class LockUtils {

    @Resource
    private RedisService redisService;

    /**
     * 该加锁方法仅针对单实例 Redis 可实现分布式加锁
     * 对于 Redis 集群则无法使用
     * 支持重复，线程安全
     *
     * @param lockKey  加锁键
     * @param clientId 加锁客户端唯一标识(采用UUID)
     * @param seconds  锁过期时间
     * @return 是否上锁成功
     */
    public synchronized boolean lock(String lockKey, String clientId, long seconds) {
        // SET命令的参数
        String value = redisService.getCacheObject(lockKey);
        if (StrUtil.isEmpty(value)) {
            redisService.setCacheObject(lockKey, clientId, seconds, TimeUnit.SECONDS);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 与 tryLock 相对应，用作释放锁
     *
     * @param lockKey  加锁键
     * @param clientId 加锁客户端唯一标识(采用UUID)
     * @return 是否成功解锁
     */
    public synchronized boolean unlock(String lockKey, String clientId) {
        String value = redisService.getCacheObject(lockKey);
        if (StrUtil.isEmpty(value)) {
            // 如果过期了也能解锁成功
            return true;
        } else {
            // 如果取出来不为空
            if (clientId.equals(value)) {
                // 并且 uuid 相等就解锁成功
                redisService.deleteObject(lockKey);
                return true;
            }
        }
        return false;
    }

}
